class AuthD::Request
	IPC::JSON.message Register, 1 do
		property login      : String
		property password   : String
		property email      : String?                  = nil
		property profile    : Hash(String, JSON::Any)? = nil

		def initialize(@login, @password, @email, @profile)
		end

		def to_s(io : IO)
			super io
			io << " (login: #{@login})"
		end

		def handle(authd : AuthD::Service, fd : Int32)
			unless authd.configuration.registrations
				return Response::ErrorRegistrationsClosed.new
			end

			if authd.users_per_login.get? @login
				return Response::ErrorAlreadyUsedLogin.new
			end

			acceptable_login_regex = "[-_ %ùÙêÊçÇéÉàÀ+a-zA-Z0-9'@.,;&]+"
			pattern = Regex.new acceptable_login_regex, Regex::Options::IGNORE_CASE
			return Response::ErrorInvalidLoginFormat.new unless pattern =~ @login

			if authd.configuration.require_email && @email.nil?
				return Response::ErrorMailRequired.new
			end

			if m = @email
				# Test on the email address format.
				grok = Grok.new [ "%{EMAILADDRESS:email}" ]
				result = grok.parse m
				email = result["email"]?

				return Response::ErrorInvalidEmailFormat.new if email.nil?

				# Verify the email address isn't already in the database.
				return Response::ErrorEmailAddressAlreadyUsed.new if authd.users_per_email.get? Base64.encode(m).chomp
			end

			# In this case we should not accept its registration.
			return Response::ErrorPasswordTooShort.new if @password.size < 15
			return Response::ErrorPasswordTooLong.new  if @password.size > 100

			uid = authd.new_uid
			password = authd.hash_password @password

			user = User.new uid, @login, password
			user.contact.pending_email = @email unless @email.nil?
			user.contact.new_activation_key

			@profile.try do |profile|
				user.profile = profile
			end

			user.date_registration = Time.local

			begin
				u_login            = user.login
				u_email            = user.contact.pending_email.not_nil!
				u_activation_token = user.contact.activation_key.not_nil!

				# Once the user is created and stored, we try to contact him.
				send_activation_token authd, u_login, u_email, u_activation_token
			rescue e
				Baguette::Log.error "mailer: #{e}"
				return Response::ErrorCannotContactUser.new
			end

			# add the user only if we were able to send the confirmation mail
			authd.users << user
			authd.new_uid_commit uid
			Response::UserAdded.new user.to_public
		end
	end
	AuthD.requests << Register
end
